ZK Calendar
Jumper Chen, Engineer, Potix Corporation
February 11, 2010
Applicable to zk-3.6.0 and later.
Introduction
After ZK Spreadsheet, the ZK Team is once again pushing the envelope with the release of ZK Calendar, a Google calendar like embeddable Ajax component for your Java applications. You are able to customize both the functionality and the style of your web calendar. One of the main benefits of ZK Calendar is the ability to interact with other Ajax components within your Web applications. Even better, your calendar event data is stored on your own database preventing exposure of sensitive data. With ZK Calendar, users of your applications are easily able to share schedules and create group calendars providing a rich Ajax experience under authority controls.
ZK Calendar schedules events in a similar fashion to Google Calendar, together with worldwide user support via multiple time zones. Within the Calendar component, there are many different dairy view modes, in the demo these include:
- Daily
- Weekly
- Every 5 days
- Monthly
The component has two main display molds, the default mold and monthly mold. While using the default mold it is possible to display any number of days on the page, however the optimum limit would be 7. In contrast, the monthly mold is solely restricted to the 「month」 view. This functionality provides users with a convenient way in which to view their schedule.
Live Demo
The following example is a CRUD calendar application demo which demonstrates how to use ZK Calendar component to implement a Google-Calendar-like web application.
You can try the live demo online or view the Flash demo below.
Layout Structure
The Calendar component only allows one child component named Toolbar. Each calendar event is manipulated by a CalendarModel, which is an interface defined to store the calendar event datum.
- 1. Default Mold
In the default mold, the content of the calendar is separated into two parts. The main component area is where date time events are displayed and the top of the Calendar component is used to display the daylong event.
The amount of days shown on the Calendar component depends on the value returned by Calendars#getDays(), if the value is seven, it will show a week per page.
- 2. Month Mold
In the month mold the date time event has no background color but the text is colored and the daylong event has a background color with white text. When utilising the month mold, each row represents one week.
Component Usage
Here is Calendar's attribute specification table:
Attribute | Usage | Default Value |
---|---|---|
readonly | Sets whether it is readonly | false |
firstDayOfWeek | Sets what the first day of the week is; e.g., SUNDAY in the U.S., MONDAY in France
|
system default |
currentDate | Sets the current date | today (depend on which timezone the system is using) |
days | Sets the days, that is, how many column should be displayed on the default mold | 7 (i.e. one week) |
dateFormatter | Sets the date formatter. In fact, there are five places in the calendar must have different date display | org.zkoss.calendar.impl.SimpleDateFormatter
|
eventRender | Sets the event renderer | org.zkoss.calendar.impl.SimpleEventRender
|
model | Sets the calendar model | null |
Event Listeners
The Calendar component provides three events. These events allow the user to execute code when a Calendar event is created, edited and updated:
1. onEventCreate:
The event is triggered when a user clicks a day which has no calendar event or drag and drops a date range onto the calendar.
2. onEventEdit:
The event is triggered by a user clicking on a calendar event.
3. onEventUpdate:
The event is triggered by a user re-sizing the date range or dragging and dropping the calendar event onto a different date.
The above video demonstrates how a popup window is used to enable the user to create a calendar event and edit it. In addition to this another popup window is used to confirm that a message has been updated, this window is then close it by a timer.
Calendar's Event
Here is a description table of the CalendarsEvent when passed by one of the three events above.
Method | Usage |
---|---|
stopClearGhost | Stops to clear the dragging ghost command |
clearGhost | Clears the dragging ghost |
getBeginDate | Returns the updated beginning date. If the event name is onEventEdit, null is assumed |
getEndDate | Returns the updated end date. If the event name is onEventEdit, null is assumed |
getCalendarEvent | Returns the calendar event. If the event name is onEventCreate, null is assumed |
getX | Returns the x coordination of the mouse pointer relevant to the component |
getY | Returns the y coordination of the mouse pointer relevant to the component |
getDesktopWidth | Returns the pixel width of the client's desktop |
getDesktopHeight | Returns the pixel height of the client's desktop |
Multi-Timezone
In the Calendar component the default time zone is the first timezone which was added. If no time zone was entered then the system』s time zone is taken as default. All the dates in the Calendar component use coordinated universal time (UTC). If you wish to show the date and time with regard to your settings (like in the demo) you will need to use the function getDefaultTimeZone() to retrieve the local time and use that to format your date and time.
For example:
SimpleDateFormat create_sdf = new SimpleDateFormat("HH:mm");
create_sdf.setTimeZone(calendars.getDefaultTimeZone());
Calendar cal = Calendar.getInstance(org.zkoss.util.Locales.getCurrent());
String[] times = create_sdf.format(evt.getBeginDate()).split(":");
int hours = Integer.parseInt(times[0])*2;
int mins = Integer.parseInt(times[1]);
if (mins >= 30) hours++;
createEvent.getFellow("ppbt").setSelectedIndex(hours);
The above example is used to display the correct time of day in a Listbox.
Calendar Event Object
We do not provide a ZK component for the calendar event object because the usage of the calendar event object is unlike a basic ZK component. Hence, we only provide an interface named CalendarEvent, which provides several getting methods used for the Calendars component. By default, we create a SimpleCalendarEvent implementation of the CalendarEvent, like a DTO. For ease of use, you can use your DTO to implement the CalendarEvent interface, and then directly use it through your web application.
Below is the description of CalendarEvent interface:
Method | Usage |
---|---|
getBeginDate | Returns the beginning date of the calendar event. |
getEndDate | Returns the end date of the calendar event.(exclusive) |
getTitle | Returns the title of the calendar event. |
getContent | Returns the content of the calendar event. |
getHeaderColor | Returns the color of the header in the calendar event. Only allows the value being recognized by CSS. |
getContentColor | Returns the color of the content in the calendar event. Only allows the value being recognized by CSS. |
getZclass | Returns the zclass of the calendar event. |
isLocked | Returns whether the calendar event is locked or not. |
Note: All of the above getting methods cannot be null.
Data Model
The only way to manipulate the calendar event object is to use the interface CalendarModel. We create an implementation of CalendarModel named SimpleCalendarModel which allows the developer to add, remove and update the calendar event object.
The best method of implementation would be to create a load-on-demand model which only retrieves the needed calendar event object, rather than storing them all.
Customization
Date Formatter
DateFormatter provides 5 functions which retrieve the caption, with four of these providing additional formatting:
- DateFormatter#getCaptionByDayOfWeek()
- Returns the caption of the day of week.
- DateFormatter#getCaptionByTimeOfDay()
- Returns the caption of the time of day.
- DateFormatter#getCaptionByDate()
- Returns the caption of the date.
- DateFormatter#getCaptionByDateOfMonth()
- Returns the caption of the date of month.
- DateFormatter#getCaptionByPopup()
- Returns the caption of the popup title.
We create an implementation of the DateFormatter interface named SimpleDateFormatter. To use your own it is possible to utilize the function setDateFormatter() of the Calendar to change the implementation.
Event Render
Since the CalendarEvent is not a ZK component we need to provide a way to render its HTML. There are four methods used to render an outline:
- EventRender#drawDay()
- Draws the day in the default mode of the calendar.
- EventRender#drawAllDay()
- Draws the all day in the default mode of the calendar.
- EventRender#drawDayByMonth()
- Draws the day in the month mode of the calendar.
- EventRender#drawAllDayByMonth()
- Draws the all day in the month mode of the calendar.
We create an implementation of the EventRender interface by default named SimpleEventRender. You can utilize the setEventRender() function of the Calendar component to change the implementation.
Note: If you change the implementation, please make sure the JavaScript of the Calendars component works well as some of the information in CalendarEvent needs to be transferred between the client and server.
FAQ
How do you display the popup window correctly upon user interaction ?
The CalendarsEvent provides the methods getX(), getY(), getDesktopWidth() and getDesktopHeight(). You can utilize these API to calculate where the calendar event should be placed.
For example:
CalendarsEvent evt = (CalendarsEvent) event;
int left = evt.getX();
int top = evt.getY();
if (top + 245 > evt.getDesktopHeight())
top = evt.getDesktopHeight() - 245;
if (left + 410 > evt.getDesktopWidth())
left = evt.getDesktopWidth() - 410;
createEvent.setLeft(left + "px");
createEvent.setTop(top + "px");
In this sample the values 245 and 410 are dependent on the height and width of your component.
How do I enable the dragging ghost of the Calendar Event ?
By default, the ghost of the dragging event will not be present. However you can invoke the stopClearGhost() method of the CalendarEvent to enable the ghost.
Note: If you make use of this functionality, you are required to invoke the clearGhost() method of the CalendarsEvent once all your logic has been completed. (There is a trick that after update the CalendarModel, the dragging ghost will be removed.)
For example,
- To enable the dragging ghost
<attribute name="onEventCreate"><![CDATA[
... // omitted
createEvent.setAttribute("calendars", cal);
createEvent.setAttribute("calevent", evt);
evt.stopClearGhost();
]]></attribute>
- To clear the dragging ghost
<button mold="os" label="Cancel">
<attribute name="onClick">
... // omitted
((org.zkoss.calendar.event.CalendarsEvent)createEvent.getAttribute("calevent")).clearGhost();
</attribute>
</button>
How to prevent a user double booking ?
There is no straightforward way to prevent a user double booking, but you can validate the calendar event date via these events, onEventCreate, onEventEdit and onEventUpdate.
What is different between the date time event and the daylong event ?
- A Date time event is an event where the start and end times occur on the same day
- A Daylong event is an event where the duration of the event is more than one day, or the start and end times are on different days
For example,
- If the start date is 2009/05/08 00:00 and the end date is 2009/05/09 00:00, the duration of the event is 1 day, therefore it is a daylong event.
- If the start date is 2009/05/08 23:00 and the end date is 2009/05/09 03:00, the start and end times are on different days, hence it is also a daylong event.
- If the start date is 2009/05/08 02:00 and the end date is 2009/05/09 00:00, the start and end times are on the same day, hence it is a date time event.
Note:
- The above conditions are dependent upon which time zone the Calendar uses
- The end date of the CalendarEvent is exclusive
- When you manipulate the date object in your web application, you must be set the MILLISECOND and SECOND fields to 0 in the java.util.Calendar object because we use the Date.getTime() in the Calendar component to compare the duration of the calendar event between the start date and the end date.
For example, we want to create a new CalendarEvent as follows:
SimpleCalendarEvent ce = new SimpleCalendarEvent();
Calendar cal = Calendar.getInstance(calendars.getDefaultTimeZone()); // create a calendar instance used to calculate the date time
Date beginDate = ppbegin.getValue(); // select a day by datebox
// just in case to clear the seconds and the millisecond.
cal.setTime(beginDate);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
beginDate = cal.getTime();
ce.setBeginDate(beginDate);
Downloads
Summary
The calendar application is one of the most fundamental applications within enterprise. Such calendar applications can be utilized to track employee hours and the amount of time they are out of the office.
Currently, you may utilize Google-Calendar or have used it in the past, this will involve making certain information public or allowing it to be accessed by Google. Utilizing this component it is possible to build a robust internal system in a quick and effective manner.
Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License. |